﻿using NUnit.Framework;
using Sasa.QualityTools.CodeAnalysis.SearchEngine.Processing;
using Sasa.QualityTools.CodeAnalysis.SearchEngine.Processing.Tokens;
using System;
using System.Collections.Generic;
using Sasa.QualityTools.CodeAnalysis.SearchEngine.Tests.Unit.Helpers;

namespace Sasa.QualityTools.CodeAnalysis.SearchEngine.Tests.Unit.Processing
{
    [TestFixture]
    public class TokenizerTest
    {
        private Tokenizer testee;


        [SetUp]
        public void SetUp()
        {
            this.testee = new Tokenizer();
        }

        [Test]
        public void TestTokenizeWithNull()
        {
            CollectionAssert.IsEmpty(this.testee.Tokenize(null));
        }

        [Test]
        public void TestTokenizeWithEmpty()
        {
            CollectionAssert.IsEmpty(this.testee.Tokenize(""));
        }

        [Test]
        public void TestTokenizeWithWhiteSpaces()
        {
            CollectionAssert.IsEmpty(this.testee.Tokenize("  \n\n   \t\t\n\r  \t  "));
        }

        [Test]
        public void TestTokenizeWithOpeningParenthesis()
        {
            CollectionAssert.AreEqual(Tokens().LPar(), this.testee.Tokenize("("));
        }

        [Test]
        public void TestTokenizeWithClosingParenthesis()
        {
            CollectionAssert.AreEqual(Tokens().RPar(), this.testee.Tokenize(")"));
        }

        [Test]
        public void TestTokenizeWithAnd()
        {
            CollectionAssert.AreEqual(Tokens().And("AND").And("and").And("And").And("aND"),
                this.testee.Tokenize("AND and And aND"));
        }

        [Test]
        public void TestTokenizeWithOr()
        {
            CollectionAssert.AreEqual(Tokens().Or("OR").Or("or").Or("Or").Or("oR"),
                this.testee.Tokenize("OR or Or oR"));
        }

        [Test]
        public void TestTokenizeWithWord()
        {
            CollectionAssert.AreEqual(Tokens().Word("word"),
                this.testee.Tokenize("word"));
        }

        [Test]
        public void TestTokenizeWithParentheticWord()
        {
            CollectionAssert.AreEqual(Tokens().LPar().Word("word").RPar(),
                this.testee.Tokenize("(word)"));
        }

        [Test]
        public void TestTokenizeWithSingleQuotedWord()
        {
            CollectionAssert.AreEqual(Tokens().Word("word1 word2 word3"),
                this.testee.Tokenize("'word1 word2 word3'"));
        }

        [Test]
        public void TestTokenizeWithUnopenedSingleQuotedWord()
        {
            CollectionAssert.AreEqual(Tokens().Word("word1").Word("word2").Word("word3'"),
                this.testee.Tokenize("word1 word2 word3'"));
        }

        [Test]
        public void TestTokenizeWithUnclosedSingleQuotedWord()
        {
            CollectionAssert.AreEqual(Tokens().Word("word1 word2 word3"),
                this.testee.Tokenize("'word1 word2 word3"));
        }

        [Test]
        public void TestTokenizeWithDoubleQuotedWord()
        {
            CollectionAssert.AreEqual(Tokens().Word("word1 word2 word3"),
                this.testee.Tokenize("\"word1 word2 word3\""));
        }

        [Test]
        public void TestTokenizeWithUnopenedDoubleQuotedWord()
        {
            CollectionAssert.AreEqual(Tokens().Word("word1").Word("word2").Word("word3\""),
                this.testee.Tokenize("word1 word2 word3\""));
        }

        [Test]
        public void TestTokenizeWithUnclosedDoubleQuotedWord()
        {
            CollectionAssert.AreEqual(Tokens().Word("word1 word2 word3"),
                this.testee.Tokenize("\"word1 word2 word3"));
        }

        [Test]
        public void TestTokenizeWithComplexText()
        {
            var text = "  word1\tword2 '' ( \"quoted ( word1\"  'quoted word2)' )  \"\"      word3 ";
            var expected = Tokens()
                .Word("word1").Word("word2")
                .LPar().Word("quoted ( word1").Word("quoted word2)").RPar()
                .Word("word3");
            CollectionAssert.AreEqual(expected, this.testee.Tokenize(text));
        }

        private IEnumerable<IToken> Tokens()
        {
            return new List<IToken>();
        }
    }
}
